package com.siwei.mes.sync.tc.service;

import cn.hutool.core.collection.CollectionUtil;
import com.siwei.mes.common.util.JsonUtils;
import com.siwei.mes.entity.experiment.*;
import com.siwei.mes.entity.materials.Materials;
import com.siwei.mes.entity.sync.tc.SupplyTask;
import com.siwei.mes.entity.sync.tc.Waybill;
import com.siwei.mes.enums.CheckEnum;
import com.siwei.mes.enums.CheckTypeEnum;
import com.siwei.mes.enums.TcContrastExperimentTypeEnum;
import com.siwei.mes.enums.WaybillStateEnum;
import com.siwei.mes.mapper.experiment.CheckQuickConfigMapper;
import com.siwei.mes.mapper.experiment.ExperimentCheckWaybillMapper;
import com.siwei.mes.mapper.experiment.ExperimentGenConfigMapper;
import com.siwei.mes.mapper.experiment.ExperimentQuickRecordMapper;
import com.siwei.mes.mapper.syncTc.SupplyTaskMapper;
import com.siwei.mes.service.materials.MaterialsService;
import com.siwei.mes.sync.tc.entity.GenMaterialResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 生成原材料快检
 *
 * @Description: 生成原材料快检
 * @Version: 1.0
 * @author: mlchen
 * @date: 2025/3/8 00:54
 */
@Service
public class GenMaterialQuickExperimentService extends GenMaterialAbstractService {

    private static final Logger log = LoggerFactory.getLogger("tc");
    /**
     * 是否是快检
     */
    private final boolean IS_QUICK = true;
    /**
     * 检测类型
     */
    private final Integer CHECK_TYPE = CheckEnum.QUICK.getCode();
    @Resource
    private ExperimentGenConfigMapper experimentGenConfigMapper;
    @Resource
    private CheckQuickConfigMapper checkQuickConfigMapper;
    @Resource
    private ExperimentQuickRecordMapper experimentQuickRecordMapper;
    @Resource
    private SupplyTaskMapper supplyTaskMapper;
    @Resource
    private ExperimentCheckWaybillMapper experimentCheckWaybillMapper;
    @Resource
    private MaterialsService materialsService;

    /**
     * 生成快检
     *
     * @param mesType 砼材类型
     * @param entity  运单信息
     */
    public GenMaterialResult genExperiment(TcContrastExperimentTypeEnum mesType, Waybill entity) {
        GenMaterialResult genMaterialResult = new GenMaterialResult();
        genMaterialResult.setIsSuccess(true);
        genMaterialResult.setCheckType(CheckEnum.QUICK.getCode());

        log.info("开始生成【{}】快检！", mesType.getName());
        log.info("运单id：【{}】运单编号：【{}】状态：【{}】，开始执行生成原材料快检记录", entity.getWaybillId(), entity.getWaybillCode(), entity.getState());
        ExperimentGenConfig genConfig = experimentGenConfigMapper.getConfig(mesType.getMesType(), CheckEnum.QUICK.getCode());

        if (genConfig == null) {
            log.info("【{}】生成委托规则配置为空，暂不生成快检！", mesType.getName());
            genMaterialResult.setErrorMsg("生成委托规则配置为空").setIsSuccess(false);
            return genMaterialResult;
        }
        if (genConfig.getIsOpen() == null || genConfig.getIsOpen() == 0) {
            log.info("【{}】生成【{}】委托规则配置暂未开启，暂不生成快检！", mesType.getName(), CheckEnum.QUICK.getName());
            genMaterialResult.setErrorMsg("委托规则配置暂未开启").setIsSuccess(false);
            return genMaterialResult;
        }
        if (!WaybillStateEnum.WAIT_WEIGH.getCode().equals(entity.getState())) {
            log.info("运单id：【{}】运单编号：【{}】状态：【{}】 状态不为待过磅，暂不生成快检！", entity.getWaybillId(), entity.getWaybillCode(), entity.getState());
            genMaterialResult.setErrorMsg("状态不为待过磅").setIsSuccess(false);
            return genMaterialResult;
        }

        SupplyTask supplyTask = supplyTaskMapper.selectByTaskId(entity.getSupplyTaskId());
        if (supplyTask == null) {
            log.info("【{}】生成委托不存在供货任务，暂不生成快检！", mesType.getName());
            genMaterialResult.setErrorMsg("生成委托不存在供货任务").setIsSuccess(false);
            return genMaterialResult;
        }

        Materials materials = materialsService.checkIsExist(mesType.getMesType(), entity.getProjectName(), entity.getProjectSpecs());
        if (materials.getSpecId() == null) {
            log.info("【{}】【{}】【{}】生成委托不存在对应材料，暂不生成快检！", mesType.getName(), materials.getMaterialName(), materials.getMaterialSpecs());
            genMaterialResult.setErrorMsg("生成委托不存在对应材料，暂不生成快检！").setIsSuccess(false);
            return genMaterialResult;
        }

        double signQuantity = this.getDoubleValue(entity.getSignQuantity());
        double genQuantity = this.getDoubleValue(entity.getGenQuickQuantity());

        /**这里直接判断 签收的方量是否等于已生成对应类型的委托的方量*/
        if (signQuantity == genQuantity) {
            log.info("运单id：【{}】运单编号：【{}】没有剩余方量可以生成快检试验台账，暂不生成快检！签收方量：【{}】，已生成快检委托数量：【{}】", entity.getWaybillId(), entity.getWaybillCode(), signQuantity, genQuantity);
            genMaterialResult.setErrorMsg("没有剩余方量可以生成快检试验台账").setIsSuccess(false);
            return genMaterialResult;
        }

        if (genQuantity > signQuantity) {
            log.info("运单id：【{}】运单编号：【{}】剩余方量大于签收方量，暂不生成快检！签收方量：【{}】，已生成快检委托数量：【{}】", entity.getWaybillId(), entity.getWaybillCode(), signQuantity, genQuantity);
            genMaterialResult.setErrorMsg("剩余方量大于签收方量，暂不生成快检！").setIsSuccess(false);
            return genMaterialResult;
        }

        log.info("运单签收方量：【{}】,已生成快检委托数量：【{}】，剩余方量：【{}】", signQuantity, genQuantity, signQuantity - genQuantity);
        /**这里判断剩余方量*/
        signQuantity = signQuantity - genQuantity;


        Integer checkRules = genConfig.getCheckRules();//规则 1-车车都检  2-按重量  3-按车数  4-按时间
        String checkThreshold = genConfig.getCheckThreshold() == null ? "0" : genConfig.getCheckThreshold();//阈值  多少吨或者多少天  根据规则来走的
        Integer qualifiedType = genConfig.getQualifiedType();//限定类型  1-同一厂家（同一配合比）   2-同一供货商（同一任务单）
        log.info("快检生成【{}】规则为：【{}】,阈值为：【{}】，限定类型：【{}】", mesType.getName(), checkRules, checkThreshold, qualifiedType);

        Long experimentId = null;// 试验台账id
        List<CheckQuickConfig> needGenQuickConfigList = new ArrayList<>();
        /**快检/批检与试验台账和运单的关系*/
        List<ExperimentCheckWaybill> needAddCheckWaybillList = new ArrayList<>();
        /**委托试验名称*/
        Set<String> entrustExperimentSet = new HashSet<>();
        /**试验项目code集合*/
        Set<String> testProjectCodeList = new HashSet<>();
        /**获取所有快检配置信息*/
        List<CheckQuickConfig> quickConfigList = checkQuickConfigMapper.select(new CheckQuickConfig().setIsDel(0).setProjectCategory(mesType.getMesType()));


        for (CheckQuickConfig quickConfig : quickConfigList) {
            /**放入试验项目code集合*/
            List<String> codeList = Arrays.asList(quickConfig.getTestProjectCode().split(","));
            /**放入委托试验名称*/
            List<String> nameList = Arrays.asList(quickConfig.getTestProjectName().split(","));
            if (!quickConfig.getCheckType().equals(CheckTypeEnum.DEFAULT_CHECK.getCode())) {
                /**判断是否将试验项目添加到实验委托中*/
                if (super.isAddExperimentByCheckType(quickConfig.getCheckType(), quickConfig.getTestProjectCode(), materials)) {
                    continue;
                }
            }
            testProjectCodeList.addAll(codeList);
            entrustExperimentSet.addAll(nameList);

            if (checkRules == 1) {//1-车车都检
                needGenQuickConfigList.add(quickConfig);
            } else if (checkRules == 2 || checkRules == 3) {//2-按重量  3-按车数
                /**查询对应快检是否有之前的台账关联关系*/
                ExperimentCheckWaybill checkWaybill = new ExperimentCheckWaybill().setCheckId(quickConfig.getId()).setCheckType(CheckEnum.QUICK.getCode())
                        .setMaterialName(materials.getMaterialName()).setMaterialSpecs(materials.getMaterialSpecs()).setExperimentType(mesType.getTcType());
                if (qualifiedType != null && qualifiedType == 1) {//1-同一厂家
                    checkWaybill.setFactory(entity.getFactory());
                } else if (qualifiedType != null && qualifiedType == 2) {//2-同一供应商(没有这个概念)
                    checkWaybill.setSupplyCompanyCompany(supplyTask.getSupplyCompanyCompany());
                }
                List<ExperimentCheckWaybill> checkList = experimentCheckWaybillMapper.getList(checkWaybill);
                if (CollectionUtil.isNotEmpty(checkList)) {
                    double totalThreshold = 0;// 之前的条数或者是方量
                    double addTotal = 0;// 本次加上之前的条数或者方量

                    if (checkRules == 3) {//3-按车数 就是运单的条数
                        totalThreshold = checkList.size();
                        addTotal = totalThreshold + 1;
                        log.info("批检【按车数】生成，当前车数：【{}】,需要添加车数：【{}】，最终车数：【{}】", totalThreshold, 1, addTotal);
                    } else {
                        totalThreshold = checkList.get(0).getBehalfNumber();
                        addTotal = totalThreshold + signQuantity;
                        log.info("批检【按重量】生成，当前重量：【{}】，运单生产方量：【{}】，最终方量：【{}】", totalThreshold, signQuantity, addTotal);
                    }
                    log.info("判断是否清理试验委托和运单之间的关系表，最终方量：【{}】，阈值方量：【{}】", addTotal, checkThreshold);

                    /**如果之前的加上本次的 大于阈值需要生产一个新的试验台账记录否则就用之前的*/
                    if (addTotal == Double.parseDouble(checkThreshold)) {
                        experimentId = checkList.get(0).getExperimentId();
                    } else if (addTotal > Double.parseDouble(checkThreshold)) {//如果大于阈值
                        log.info("如果之前的加上本次的大于阈值需要生产一个新的试验台账记录，开始清空experimentCheckWaybill表数据");
                        needGenQuickConfigList.add(quickConfig);
                        for (ExperimentCheckWaybill checkWaybillInfo : checkList) {
                            log.info("开始清空experimentCheckWaybill表数据，数据：【{}】", JsonUtils.getJson(checkWaybillInfo));
                            experimentCheckWaybillMapper.deleteByPrimaryKey(checkWaybillInfo.getId());
                        }
                    } else {
                        if (!checkList.isEmpty()) {
                            experimentId = checkList.get(0).getExperimentId();
                            log.info("试验委托和运单之间的关系表不为空，直接取第一条的试验委托，委托id：【{}】", experimentId);
                        } else {
                            experimentId = null;
                            log.info("试验委托和运单之间的关系表为空，需要重新生成试验委托！");
                        }
                    }
                } else {
                    experimentId = null;
                }
                /**组装快检/批检与试验台账和运单的关系*/
                ExperimentCheckWaybill checkInfo = new ExperimentCheckWaybill()
                        .setCheckId(quickConfig.getId()).setFactory(entity.getFactory()).setSupplyTaskCode(supplyTask.getSupplyTaskCode())
                        .setCheckType(CheckEnum.QUICK.getCode()).setCreateTime(new Date()).setWaybillId(entity.getId()).setSupplyCompanyCompany(entity.getSupplyCompanyCompany())
                        .setExperimentId(experimentId);
                needAddCheckWaybillList.add(checkInfo);
            } else if (checkRules == 4) {//4-按时间
                /**组装快检/批检与试验台账和小票的关系*/
                ExperimentCheckWaybill checkInfo = new ExperimentCheckWaybill()
                        .setCheckId(quickConfig.getId()).setFactory(entity.getFactory()).setSupplyTaskCode(supplyTask.getSupplyTaskCode())
                        .setCheckType(CheckEnum.QUICK.getCode()).setCreateTime(new Date()).setWaybillId(entity.getId()).setSupplyCompanyCompany(entity.getSupplyCompanyCompany())
                        .setExperimentId(experimentId);

                /**查询对应快检是否有之前的台账关联关系*/
                ExperimentCheckWaybill checkWaybill = new ExperimentCheckWaybill().setCheckId(quickConfig.getId()).setCheckType(CheckEnum.QUICK.getCode())
                        .setMaterialName(materials.getMaterialName()).setMaterialSpecs(materials.getMaterialSpecs()).setExperimentType(mesType.getTcType());
                if (qualifiedType != null && qualifiedType == 1) {//1-同一厂家（同一配合比）
                    checkWaybill.setFactory(entity.getFactory());
                } else if (qualifiedType != null && qualifiedType == 2) {//2-同一批次(没有这个概念)
                    /*checkWaybill.setSupplyTaskCode(supplyTask.getSupplyTaskCode());*/
                    checkWaybill.setSupplyCompanyCompany(entity.getSupplyCompanyCompany());
                }
                List<ExperimentCheckWaybill> checkList = experimentCheckWaybillMapper.getList(checkWaybill);
                if (!checkList.isEmpty()) {
                    experimentId = checkList.get(0).getExperimentId();
                } else {
                    /**进入这里说明之前没有数据 需要新增试验委托*/
                    experimentId = null;
                    needGenQuickConfigList.add(quickConfig);
                }
                needAddCheckWaybillList.add(checkInfo);
            }
        }

        /**如果试验台账id为空 就需要生成一个新的  如果有就只要加对应的子表记录 共用之前的试验台账记录*/
        if (experimentId == null) {
            String entrustExperiment = null;
            if (!entrustExperimentSet.isEmpty()) {
                entrustExperiment = entrustExperimentSet.stream().map(String::valueOf).collect(Collectors.joining(","));
            }

            /**新增原材料试验台账*/
            Experiment experiment = super.createExperimentInfoByWaybillInfo(mesType, CHECK_TYPE, entity, supplyTask, materials, signQuantity, entrustExperiment, testProjectCodeList);
            /**这里赋值对应的试验台账信息*/
            experimentId = experiment.getId();
        }

        /**新增试验台账对应快检配置记录*/
        for (CheckQuickConfig quickConfig : needGenQuickConfigList) {
            experimentQuickRecordMapper.insertSelective(new ExperimentQuickRecord().tcInit(true).setExperimentId(experimentId).setQuickId(quickConfig.getId()));
        }
        /**试验委托和运单关系、试验委托和供货任务关系、修改运单状态*/
        super.handleExperimentRelations(experimentId, entity.getId(), supplyTask.getSupplyTaskId(), signQuantity, IS_QUICK);

        log.info("快检【{}】，生成完毕。对应试验委托id:[{}]", mesType.getName(), experimentId);
        genMaterialResult.setExperimentIdList(Collections.singletonList(experimentId));
        return genMaterialResult;
    }
}
